package org.raymond.iworks.study.basic.thread.visibility;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDateTime;

/**
 * @author raymond
 * @version V1.0
 * @Description:
 * volatile: 协议缓存一致性+总线嗅探机制
 * 协议缓存一致性包括MSI,MESI,MOSE等,Intel的MESI
 * MESI(M-Modify,E-Exclusive,S-Share,I-Invalid)
 * CPU1 从主内存读取变量到CacheLine,如果该变量未标记过,则标记为E
 * CPU2 从主内存读取变量到CacheLine,因CPU1也有此变量,CPU1和CPU2都标记为S
 * CPU1 修改CacheLine中的变量,标记为M,与主内存不一致,CPU2将标记为I,变量值写入主内存
 * CPU2 读取标记为I的变量,该变量无效,CPU2从主内存读取,重新标记为S
 *
 */
@Slf4j
public class HelloVolatile {
    // synchronized 保证可见性, 将cpu缓存数据同步到内存
    // volatile 没有这个关键字时,修改running变量无效
    // volatile,
    private static /*volatile*/ boolean running = true;

    private static void m(){
        System.out.println(LocalDateTime.now()+":m start");
        while(running){
            // 没有volatile关键字,但如果这里执行了语句,则会通过synchronized关键字
            // 将cpu的缓存的内容刷到内存里,从而使runnning对其他线程可见
            // System.out.println(LocalDateTime.now()+":hello");
        }
        System.out.println(LocalDateTime.now()+":m end");
    }
    public static void main(String[] args) throws InterruptedException, IOException {
        new Thread(HelloVolatile::m).start();

        Thread.sleep(1000);


        running = false;

        System.in.read();
    }
}
